


/*
	MIT License

	Copyright (c) 2025 xLeaves [xywhsoft] <xywhsoft@qq.com>

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
	SOFTWARE.
*/



/*
	符号列表：
		{						模板起始符号				需要转义				{{
		! $ % & ? * = @ #		模板操作符号				不需要转义
		:						参数分隔符				需要转义				\:
		}						模板结束符号				需要转义				\}
		\						语句内转义符号			语句内需要转义		\\
*/



/*
	高级语法：
		
		1. define : 注册子模板，子模板可使用 {=子模板名称}、{*变量值:子模板名称} 等方式代入
			{#define:子模板名称}
				子模板内容
			{#end}
			注：子模板不可嵌套，内部可使用 {$__self} 变量访问代入值
		
		2. if : 条件判断
			{#if:表达式}
				语句
			{#elseif:表达式}
				语句
			{#else}
				语句
			{#end}
			注：xTemplateEngine 不对表达式做处理，不要宿主程序自行解析
		
		3. for
			{#for:1:10:1}
				语句
			{#end}
			注：内部可使用 {#__index} 访问当前循环索引
		
		4. foreach
			{#foreach:变量名}
				语句
			{#end}
			注：内部可使用 {#__index} 访问当前循环索引，{$__value} 访问当前值（如果当前值是字符串的话）
		
		5. script
			{#script:脚本语言}
				语句
			{#end}
			注：脚本语句块不可嵌套，另外脚本语句块不解析任何转义符，只在遇到 {#end} 时结束语句
		
		6. include
			{#include:文件名}
		
*/



#include "xtemplate.h"



// 字符串对比函数（strncmp）
#define XTE_STRNCMP		strncasecmp



// 错误列表
/*
	0		成功							success
	1		内存申请失败					malloc failed
	2		Token 列表添加失败			token list append failed
	3		无法识别的符号				unrecognized symbols
	4		不允许使用空符号				empty symbols are not allowed
	5		参数数量过多					too many parameters
	6		语句未结束					statement not ended
	7		未定义标识符					Undefined identifier
*/
const char* XTE_ERROR_DESC[] = {
	"success",
	"malloc failed",
	"token list append failed",
	"unrecognized symbols",
	"empty symbols are not allowed",
	"too many parameters",
	"statement not ended",
	"Undefined identifier",
	"Missing parameters",
	"Nesting of define statements is not allowed.",
	"syntax error"
};



// 内存申请失败错误返回对象（避免返回 NULL）
XTE_TokenList_Struct XTE_LEXER_ERROR_MALLOC = {
	0,
	1,
	"malloc failed",
	0,
	0,
	0,
	0,
	0,
	0,
	{
		NULL,
		0,
		0,
		0,
		0
	}
};



// 创建关键字列表（失败返回 NULL）
XTE_IdentList xteCreateIdentList()
{
	return SAMM_Create(sizeof(XTE_IdentInfo_Struct));
}

// 销毁关键字列表
void xteDestroyIdentList(XTE_IdentList objList)
{
	if ( objList ) {
		for ( int i = 1; i <= objList->Count; i++ ) {
			XTE_IdentInfo objID = SAMM_GetPtr_Unsafe(objList, i);
			if ( objID->Ident ) {
				free(objID->Ident);
			}
		}
		SAMM_Destroy(objList);
	}
}

// 添加一个关键字到列表
int xteAddIdentToList(XTE_IdentList objList, char* sID, unsigned int iSize, unsigned int iIndex, unsigned int iType, unsigned int iMinParamCount, unsigned int iMaxParamCount)
{
	// 自动计算关键字长度
	if ( iSize == 0 ) {
		iSize = strlen(sID);
		if ( iSize == 0 ) {
			return 0;
		}
	}
	if ( objList ) {
		// 创建关键字字符串副本
		char* sKey = malloc(iSize + 1);
		if ( sKey == NULL ) {
			return 0;
		}
		memcpy(sKey, sID, iSize);
		sKey[iSize] = 0;
		// 添加关键字到列表
		unsigned int idx = SAMM_Append(objList, 1);
		if ( idx == 0 ) {
			free(sKey);
			return 0;
		}
		XTE_IdentInfo objID = SAMM_GetPtr_Unsafe(objList, idx);
		objID->Ident = sKey;
		objID->TokenIndex = iIndex;
		objID->Type = iType;
		objID->Size = iSize;
		objID->MinParamCount = iMinParamCount;
		objID->MaxParamCount = iMaxParamCount;
		objID->Hash = Hash32(sKey, iSize);
		return idx;
	}
	return 0;
}



// 构建分词器解析错误
#define XTE_OnLexerError(id) { objRet->Success=0; objRet->ErrorCode=id; objRet->ErrorDesc=XTE_ERROR_DESC[id]; objRet->ErrorLine=iLine; objRet->ErrorLinePos=iLinePos; objRet->ErrorPos=i; objRet->ErrorRefLine=iRefLine; objRet->ErrorRefLinePos=iRefLinePos; objRet->ErrorRefPos=iRefPos; if(objBuf){MBMU_Destroy(objBuf);}; xte_private_free_tokenlist(&objRet->Tokens); return objRet; }



// 释放 XTE_TokenList
void xte_private_free_tokenlist(SAMM_Object arrToken)
{
	if ( arrToken->Memory ) {
		for ( int i = 1; i <= arrToken->Count; i++ ) {
			XTE_TokenItem objTok = SAMM_GetPtr_Unsafe(arrToken, i);
			if ( objTok->Text ) {
				free(objTok->Text);
			}
			for ( int iParam = 0; iParam < objTok->ParamCount; iParam++ ) {
				if ( objTok->ParamText[iParam] ) {
					free(objTok->ParamText[iParam]);
				}
			}
		}
		SAMM_Unit(arrToken);
	}
}
void xteLexerFree(XTE_TokenList arrToken)
{
	if ( arrToken != &XTE_LEXER_ERROR_MALLOC ) {
		xte_private_free_tokenlist(&arrToken->Tokens);
		free(arrToken);
	}
}

// 解析模板文件为 Token 列表
XTE_TokenList xteLexer(char* sText, size_t iSize, XTE_IdentList objIdentList, char* sBracket)
{
	// 创建返回值结构体
	XTE_TokenList objRet = malloc(sizeof(XTE_TokenList_Struct));
	if ( objRet == NULL ) {
		return &XTE_LEXER_ERROR_MALLOC;
	}
	objRet->ErrorLine = 0;
	objRet->ErrorLinePos = 0;
	objRet->ErrorPos = 0;
	objRet->ErrorRefLine = 0;
	objRet->ErrorRefLinePos = 0;
	objRet->ErrorRefPos = 0;
	SAMM_Init(&objRet->Tokens, sizeof(XTE_TokenItem_Struct));
	// 自动计算文本长度
	if ( iSize == 0 ) {
		iSize = strlen(sText);
		if ( iSize == 0 ) {
			objRet->Success = -1;
			objRet->ErrorCode = 0;
			objRet->ErrorDesc = XTE_ERROR_DESC[0];
			return objRet;
		}
	}
	// 默认使用花括号作为模板符号
	if ( sBracket == NULL ) {
		sBracket = "{}";
	}
	// 行号信息
	size_t i = 0;
	size_t iPos = 0;
	size_t iRefLine = 1;
	size_t iRefLinePos = 1;
	size_t iRefPos = 0;
	size_t iLine = 1;
	size_t iLinePos = 0;
	// 创建临时缓冲区对象
	MBMU_Object objBuf = MBMU_Create(0, 0x10000);
	if ( objBuf == NULL ) {
		XTE_OnLexerError(1);
	}
	// 遍历获取 Token
	int iMode = XTE_TK_TEXT;
	XTE_TokenItem objCurTok;
	size_t iSkip = 0;
	for ( i = 0; i < iSize; i++ ) {
		// 处理行号和行位置
		if ( sText[i] == '\n' ) {
			iLine++;
			iLinePos = 0;
		} else if ( sText[i] != '\r' ) {
			iLinePos++;
		}
		// 处理跳过字符
		if ( iSkip ) {
			iSkip--;
			continue;
		}
		// Token 扫描逻辑
		if ( iMode == XTE_TK_TEXT ) {
			// XTE_TK_TEXT 采集模式
			if ( sText[i] == sBracket[0] ) {
				if ( sText[i + 1] == sBracket[0] ) {
					// 处理 {{ 转义符
					MBMU_Append(objBuf, &sText[iPos], (i - iPos) + 1, MBMU_UTF8);
					iSkip++;
					iPos = i + 2;
				} else {
					// 将符号前的内容添加到临时缓冲区
					if ( i > iPos ) {
						MBMU_Append(objBuf, &sText[iPos], i - iPos, MBMU_UTF8);
					}
					// 如果临时缓冲区存在数据，则创建一个 XTE_TK_TEXT 节点
					if ( objBuf->Length > 0 ) {
						unsigned int idx = SAMM_Append(&objRet->Tokens, 1);
						if ( idx == 0 ) {
							XTE_OnLexerError(2);
						}
						XTE_TokenItem objTok = SAMM_GetPtr_Unsafe(&objRet->Tokens, idx);
						objTok->Type = XTE_TK_TEXT;
						objTok->Text = malloc(objBuf->Length + 1);
						if ( objTok->Text == NULL ) {
							XTE_OnLexerError(1);
						}
						objTok->Size = objBuf->Length;
						memcpy(objTok->Text, objBuf->Buffer, objBuf->Length);
						objTok->Text[objBuf->Length] = 0;
						objTok->ParamCount = 0;
						objTok->IdentInfo = NULL;
						objTok->RefLine = iRefLine;
						objTok->RefLinePos = iRefLinePos;
						objTok->RefPos = iRefPos + 1;
						objTok->RefSize = i - iRefPos;
						MBMU_Clear(objBuf);
					}
					// 更新引用位置信息
					iRefLine = iLine;
					iRefLinePos = iLinePos;
					iRefPos = i;
					// 创建一个新的 TokenItem
					unsigned int idx = SAMM_Append(&objRet->Tokens, 1);
					if ( idx == 0 ) {
						XTE_OnLexerError(2);
					}
					objCurTok = SAMM_GetPtr_Unsafe(&objRet->Tokens, idx);
					// 根据下一个符号判断 Token 类型
					if ( sText[i + 1] == '!' ) {
						objCurTok->Type = XTE_TK_COMMEN;
					} else if ( sText[i + 1] == '$' ) {
						objCurTok->Type = XTE_TK_VAR;
					} else if ( sText[i + 1] == '%' ) {
						objCurTok->Type = XTE_TK_NUM;
					} else if ( sText[i + 1] == '&' ) {
						objCurTok->Type = XTE_TK_TIME;
					} else if ( sText[i + 1] == '?' ) {
						objCurTok->Type = XTE_TK_BOOL;
					} else if ( sText[i + 1] == '*' ) {
						objCurTok->Type = XTE_TK_ARR;
					} else if ( sText[i + 1] == '@' ) {
						objCurTok->Type = XTE_TK_PROC;
					} else if ( sText[i + 1] == '=' ) {
						objCurTok->Type = XTE_TK_SUBTEMPLATE;
					} else if ( sText[i + 1] == '#' ) {
						if ( objIdentList ) {
							objCurTok->Type = XTE_TK_SYMBOL;
						} else {
							// objIdentList 传递为空时，不支持 {# xxx } 的写法
							XTE_OnLexerError(3);
						}
					} else {
						// 无法识别的 Token 类型
						XTE_OnLexerError(3);
					}
					// 切换为对应的 Token 信息采集模式
					iMode = objCurTok->Type;
					objCurTok->Size = 0;
					objCurTok->Text = NULL;
					objCurTok->ParamCount = 0;
					for ( int iParam = 0; iParam < XTE_PARAM_MAXCOUNT; iParam++ ) {
						objCurTok->ParamText[iParam] = NULL;
						objCurTok->ParamSize[iParam] = 0;
					}
					objCurTok->IdentInfo = NULL;
					objCurTok->RefLine = iRefLine;
					objCurTok->RefLinePos = iRefLinePos;
					objCurTok->RefPos = iRefPos + 1;
					iSkip++;
					iPos = i + 2;
				}
			}
		} else if ( iMode == XTE_MODE_BLOCK ) {
			// XTE_MODE_BLOCK 采集模式（只在遇到 {#end} 时退出）
			if ( (sText[i] == sBracket[0]) && (sText[i+1] == '#') && (sText[i+2] == 'e') && (sText[i+3] == 'n') && (sText[i+4] == 'd') && (sText[i+5] == sBracket[1]) ) {
				objCurTok->Size = i - iPos;
				objCurTok->Text = malloc(objCurTok->Size + 1);
				if ( objCurTok->Text == NULL ) {
					XTE_OnLexerError(1);
				}
				memcpy(objCurTok->Text, &sText[iPos], objCurTok->Size);
				objCurTok->Text[objCurTok->Size] = 0;
				// 更新引用位置信息
				iRefLine = iLine;
				iRefLinePos = iLinePos + 6;
				objCurTok->RefSize = i - iRefPos + 6;
				iRefPos = i + 6;
				// 语句结束，切换为文本采集模式
				iSkip += 5;
				iPos = i + 6;
				iMode = XTE_TK_TEXT;
			}
		} else if ( iMode == XTE_TK_COMMEN ) {
			// XTE_TK_COMMEN 采集模式（跳过转义符，不处理参数列表，这样可以加快效率）
			if ( sText[i] == '\\' ) {
				// 转义符处理
				iSkip++;
			} else if ( sText[i] == sBracket[1] ) {
				// 语句结尾处理
				objCurTok->Size = i - iPos;
				if ( objCurTok->Size > 0 ) {
					objCurTok->Text = malloc(objCurTok->Size + 1);
					if ( objCurTok->Text == NULL ) {
						XTE_OnLexerError(1);
					}
					memcpy(objCurTok->Text, &sText[iPos], objCurTok->Size);
					objCurTok->Text[objCurTok->Size] = 0;
				}
				objCurTok->ParamCount = 0;
				// 更新引用位置信息
				iRefLine = iLine;
				iRefLinePos = iLinePos + 1;
				objCurTok->RefSize = i - iRefPos + 1;
				iRefPos = i + 1;
				// 语句结束，切换为文本采集模式
				iMode = XTE_TK_TEXT;
				iPos = i + 1;
			}
		} else {
			// 通用 XTE_TK_* 的 Token 信息采集模式
			if ( sText[i] == '\\' ) {
				// 转义符处理
				if ( i > iPos ) {
					MBMU_Append(objBuf, &sText[iPos], i - iPos, MBMU_UTF8);
				}
				iSkip++;
				MBMU_Append(objBuf, &sText[i+1], 1, MBMU_UTF8);
				iPos = i + 2;
			} else if ( (sText[i] == ':') || (sText[i] == sBracket[1]) ) {
				// 参数处理
				if ( i > iPos ) {
					MBMU_Append(objBuf, &sText[iPos], i - iPos, MBMU_UTF8);
				}
				// 如果 objCurTok->Text 为 NULL 则将 objBuf 传递给 objCurTok->Text，否则传递到 ParamText
				if ( objCurTok->Text ) {
					if ( objCurTok->ParamCount < XTE_PARAM_MAXCOUNT ) {
						// 如果是 {# xxx } 语句，检查参数数量是否超出允许最大数量
						if ( objCurTok->IdentInfo ) {
							if ( objCurTok->ParamCount >= objCurTok->IdentInfo->MaxParamCount ) {
								// 参数数量超出允许的最大数量
								XTE_OnLexerError(5);
							}
						}
						// 更新参数数据
						objCurTok->ParamSize[objCurTok->ParamCount] = objBuf->Length;
						if ( objBuf->Length > 0 ) {
							objCurTok->ParamText[objCurTok->ParamCount] = malloc(objBuf->Length + 1);
							if ( objCurTok->ParamText[objCurTok->ParamCount] == NULL ) {
								XTE_OnLexerError(1);
							}
							memcpy(objCurTok->ParamText[objCurTok->ParamCount], objBuf->Buffer, objBuf->Length);
							objCurTok->ParamText[objCurTok->ParamCount][objBuf->Length] = 0;
						}
						objCurTok->ParamCount++;
					} else {
						// 参数数量超出允许的最大数量
						XTE_OnLexerError(5);
					}
				} else {
					if ( objBuf->Length > 0 ) {
						// 如果是 {# xxx } 语句，先判断是否支持对应关键字
						if ( objCurTok->Type == XTE_TK_SYMBOL ) {
							unsigned int iHash = 0;
							for ( int iIdent = 1; iIdent <= objIdentList->Count; iIdent++ ) {
								XTE_IdentInfo objID = SAMM_GetPtr_Unsafe(objIdentList, iIdent);
								if ( objID->Size == objBuf->Length ) {
									if ( iHash == 0 ) {
										iHash = Hash32(objBuf->Buffer, objBuf->Length);
									}
									if ( objID->Hash == iHash ) {
										if ( XTE_STRNCMP(objBuf->Buffer, objID->Ident, objBuf->Length) == 0 ) {
											objCurTok->IdentInfo = objID;
											break;
										}
									}
								}
							}
							// 找不到标识符时，报错
							if ( objCurTok->IdentInfo == NULL ) {
								XTE_OnLexerError(7);
							}
							// 使用标识符对应的分类覆盖 XTE_TK_SYMBOL
							objCurTok->Type = objCurTok->IdentInfo->TokenIndex;
						}
						// 更新 Text 及关联字段
						objCurTok->Size = objBuf->Length;
						objCurTok->Text = malloc(objCurTok->Size + 1);
						if ( objCurTok->Text == NULL ) {
							XTE_OnLexerError(1);
						}
						memcpy(objCurTok->Text, objBuf->Buffer, objBuf->Length);
						objCurTok->Text[objCurTok->Size] = 0;
					} else {
						// objCurTok->Text 不允许 0 长度
						XTE_OnLexerError(4);
					}
				}
				MBMU_Clear(objBuf);
				iPos = i + 1;
				// 语句结尾处理
				if ( sText[i] == sBracket[1] ) {
					if ( objCurTok->IdentInfo ) {
						// 如果是 {# xxx } 语句，检查参数数量是否低于允许最小数量
						if ( objCurTok->ParamCount < objCurTok->IdentInfo->MinParamCount ) {
							XTE_OnLexerError(8);
						}
						// 语句块采集类，进入专用的处理流程
						if ( objCurTok->IdentInfo->Type == XTE_IDTPE_BLOCK ) {
							free(objCurTok->Text);
							objCurTok->Text = NULL;
							iMode = XTE_MODE_BLOCK;
						}
					}
					// 直接结束的语句，更新引用位置信息，切换为文本采集模式
					if ( iMode != XTE_MODE_BLOCK ) {
						iRefLine = iLine;
						iRefLinePos = iLinePos + 1;
						objCurTok->RefSize = i - iRefPos + 1;
						iRefPos = i + 1;
						iMode = XTE_TK_TEXT;
					}
				}
			}
		}
	}
	// 收尾操作
	if ( iMode == XTE_TK_TEXT ) {
		// 如果临时缓冲区存在数据，将尾部字符串添加为 XTE_TK_TEXT 节点
		if ( i > iPos ) {
			MBMU_Append(objBuf, &sText[iPos], i - iPos, MBMU_UTF8);
		}
		if ( objBuf->Length > 0 ) {
			unsigned int idx = SAMM_Append(&objRet->Tokens, 1);
			if ( idx == 0 ) {
				XTE_OnLexerError(2);
			}
			XTE_TokenItem objTok = SAMM_GetPtr_Unsafe(&objRet->Tokens, idx);
			objTok->Type = XTE_TK_TEXT;
			objTok->Text = malloc(objBuf->Length + 1);
			if ( objTok->Text == NULL ) {
				XTE_OnLexerError(1);
			}
			objTok->Size = objBuf->Length;
			memcpy(objTok->Text, objBuf->Buffer, objBuf->Length);
			objTok->Text[objBuf->Length] = 0;
			objTok->ParamCount = 0;
			objTok->RefLine = iRefLine;
			objTok->RefLinePos = iRefLinePos;
			objTok->RefPos = iRefPos + 1;
			objTok->RefSize = i - iRefPos;
			MBMU_Clear(objBuf);
		}
	} else {
		// 如果仍进行 XTE_TK_* 信息采集，代表词法有错误，语句没有正确结束
		XTE_OnLexerError(6);
	}
	// 返回 Token 列表
	objRet->Success = -1;
	objRet->ErrorCode = 0;
	objRet->ErrorDesc = XTE_ERROR_DESC[0];
	return objRet;
}







// 简单版模板引擎语法转换套件（编译后得到一个列表，不支持语法结构）
/*
	支持的写法：
		{!xxx}				注释
		{$xxx}				代入变量
		{%xxx}				代入数组变量
		{&xxx}				代入时间变量
		{?xxx}				根据变量逻辑值代入不用内容
		{*xxx}				代入数组变量（套子模板）
		{=xxx}				代入子变量（可指定代入值，代入值可以是任何数据类型，__self 表示代入值）
		{@xxx}				代入函数运行结果
		{#include}			引用文件（需要自行处理文件I/O）
		{#define}			定义子模板
		{#script}			运行脚本块（可指定脚本引擎）
*/



// 内存申请失败错误返回对象（避免返回 NULL）
XTE_LiteStruct XTE_LITE_ERROR_MALLOC = {
	0,
	1,
	"malloc failed",
	0,
	0,
	0,
	0,
	0,
	0,
	NULL,
	{
		NULL,
		0,
		0,
		0
	},
	{
		{
			NULL,
			0,
			NULL,
			NULL,
			{
				0,
				{
					0,
					0,
					{
						NULL,
						0,
						0,
						0
					},
					NULL
				},
				NULL,
				NULL,
				NULL,
				NULL,
				NULL
			},
			NULL,
			NULL
		}
		#ifdef MMU_USE_MP256
			,NULL
		#endif
	}
};



// xTemplate Engine Lite 模板管理器数据结构
typedef struct {
	AVLHT32_Struct Templates;					// 已加载模板列表（哈希表）
} XTE_LiteManageStruct, *XTE_LiteManage;



// 构建语法器解析错误
#define XTE_OnParseError(id) { objRet->Success=0; objRet->ErrorCode=id; objRet->ErrorDesc=XTE_ERROR_DESC[id]; objRet->ErrorLine=objTok->RefLine; objRet->ErrorLinePos=objTok->RefLinePos; objRet->ErrorPos=objTok->RefPos; if(objRefTok){ objRet->ErrorRefLine=objRefTok->RefLine; objRet->ErrorRefLinePos=objRefTok->RefLinePos; objRet->ErrorRefPos=objRefTok->RefPos; }else{ objRet->ErrorRefLine=objTok->RefLine; objRet->ErrorRefLinePos=objTok->RefLinePos; objRet->ErrorRefPos=objTok->RefPos; } return objRet; }



// 将 XTE_TokenList 转换为 XTE_LiteObject（XTE_TokenList将被释放）
XTE_LiteObject xteLiteParseFromTokenList(XTE_TokenList objToks)
{
	// 创建返回值结构体
	XTE_LiteObject objRet = malloc(sizeof(XTE_LiteStruct));
	if ( objRet == NULL ) {
		xteLexerFree(objToks);									// 如果一开始就失败了，objToks 会被无条件释放
		return &XTE_LITE_ERROR_MALLOC;
	}
	// Token 必须解析成功，否则返回 Lexer 报告的错误
	if ( objToks->Success == 0 ) {
		objRet->Success = 0;
		objRet->ErrorCode = objToks->ErrorCode;
		objRet->ErrorDesc = objToks->ErrorDesc;
		objRet->ErrorLine = objToks->ErrorLine;
		objRet->ErrorLinePos = objToks->ErrorLinePos;
		objRet->ErrorPos = objToks->ErrorPos;
		objRet->ErrorRefLine = objToks->ErrorRefLine;
		objRet->ErrorRefLinePos = objToks->ErrorRefLinePos;
		objRet->ErrorRefPos = objToks->ErrorRefPos;
		xteLexerFree(objToks);									// 如果一开始就失败了，objToks 会被无条件释放
		return objRet;
	}
	// 保存 objToks 的 Tokens，而 objToks 本体将被释放
	objRet->Tokens = &objToks->Tokens;
	if ( objToks != &XTE_LEXER_ERROR_MALLOC ) {
		free(objToks);
	}
	// 初始化数据结构
	PAMM_Init(&objRet->Actions);
	AVLHT32_Init(&objRet->SubTemplates, sizeof(PAMM_Struct));
	// 遍历 Token 列表，添加到 Actions 列表
	XTE_TokenItem objRefTok = NULL;
	PAMM_Object objCurTemplate = NULL;
	for ( int i = 1; i <= objToks->Tokens.Count; i++ ) {
		XTE_TokenItem objTok = SAMM_GetPtr_Unsafe(&objToks->Tokens, i);
		if ( objTok->Type == XTE_TK_DEFINE ) {
			// 定义子模板语句开始
			if ( objCurTemplate ) {
				XTE_OnParseError(9);
			} else {
				objCurTemplate = AVLHT32_Set(&objRet->SubTemplates, objTok->ParamText[0], objTok->ParamSize[0], NULL);
				if ( objCurTemplate == NULL ) {
					XTE_OnParseError(2);
				}
				objRefTok = objTok;
				PAMM_Init(objCurTemplate);
			}
		} else if ( objTok->Type == XTE_TK_END ) {
			// 语句结束
			if ( objCurTemplate ) {
				objCurTemplate = NULL;
			} else {
				XTE_OnParseError(10);
			}
		} else if ( objTok->Type == XTE_TK_COMMEN ) {
			// 丢弃注释语句
		} else {
			// 其他语句、指令或文本块（根据当前子模板决定存入位置）
			if ( objCurTemplate ) {
				unsigned int idx = PAMM_Append(objCurTemplate, objTok);
				if ( idx == 0 ) {
					XTE_OnParseError(2);
				}
			} else {
				unsigned int idx = PAMM_Append(&objRet->Actions, objTok);
				if ( idx == 0 ) {
					XTE_OnParseError(2);
				}
			}
		}
	}
	// 返回 Token 列表
	objRet->Success = -1;
	objRet->ErrorCode = 0;
	objRet->ErrorDesc = XTE_ERROR_DESC[0];
	return objRet;
}



// 解析返回语法列表
XTE_IdentList XTE_LITE_IDENT_LIST = NULL;
XTE_LiteObject xteLiteParse(char* sText, size_t iSize, char* sBracket)
{
	// 创建可解析的标识符列表
	if ( XTE_LITE_IDENT_LIST == NULL ) {
		XTE_LITE_IDENT_LIST = xteCreateIdentList();
		if ( XTE_LITE_IDENT_LIST == NULL ) {
			return &XTE_LITE_ERROR_MALLOC;
		}
		xteAddIdentToList(XTE_LITE_IDENT_LIST, "end"	, 3, XTE_TK_END		, XTE_IDTPE_DEFAULT	, 0, 0);
		xteAddIdentToList(XTE_LITE_IDENT_LIST, "include", 7, XTE_TK_INCLUDE	, XTE_IDTPE_DEFAULT	, 1, 1);
		xteAddIdentToList(XTE_LITE_IDENT_LIST, "define"	, 6, XTE_TK_DEFINE	, XTE_IDTPE_DEFAULT	, 1, 1);
		xteAddIdentToList(XTE_LITE_IDENT_LIST, "script"	, 6, XTE_TK_SCRIPT	, XTE_IDTPE_BLOCK	, 1, 1);
	}
	// 词法解析
	XTE_TokenList objToks = xteLexer(sText, iSize, XTE_LITE_IDENT_LIST, sBracket);
	// 语法解析
	return xteLiteParseFromTokenList(objToks);
}



// 释放 XTE_LiteObject 对象
int xte_private_free_subtemplate(Hash32_Key* pKey, PAMM_Object objAction, void* pArg)
{
	PAMM_Unit(objAction);
	return 0;
}
void xteLiteParseFree(XTE_LiteObject objLite)
{
	if ( objLite != &XTE_LITE_ERROR_MALLOC ) {
		AVLHT32_Walk(&objLite->SubTemplates, (void*)xte_private_free_subtemplate, NULL);
		AVLHT32_Unit(&objLite->SubTemplates);
		PAMM_Unit(&objLite->Actions);
		xte_private_free_tokenlist(objLite->Tokens);
		free(objLite);
	}
}







// 完整版模板引擎语法转换套件
/*
	支持的写法（包含简单版支持的所有写法，这里只列出额外支持的）：
		{#if:xxx} ... {#elseif:xxx} ... {#else} ... {#end}			条件判断语句
		{#for:1:10:1} ... {#end}									计次循环语句（可代入 __index）
		{#foreach:xxx} ... {#end}									迭代循环语句（可代入 __index、__value）
	支持自定义语句：
		{#xxx:xxx...}												自定义单标签语句
		{#xxx:xxx...} ... {#end}									自定义语句块
	高级语法支持嵌套使用，自定义语句仅提供有限的支持
*/
#ifdef XTE_USE_FULL
	
	
	
	// 
	
	
	
#endif







// 值管理器 + 页面生成套件
/*
	数据类型：
		bool		int别名，0=FALSE，else=TRUE
		int			64位
		float		64位
		text		任意长度字符串
		array		数组
		table		表
		coutom		自定义类型
*/



// 引入 ldouble 库用于数字和字符串相互转换
#include "jnum.h"



// NULL 值（不要修改这个值）
XTE_ValueStruct XTE_VALUE_NULL = {
	XTE_DT_NULL,
	0,
	0,
	0
};



// 引用计数操作
void xteValueRef(XTE_Value objVal)
{
	if ( objVal && (objVal != &XTE_VALUE_NULL) ) {
		objVal->RefCount++;
	}
}
#define xteValueFree	xteValueUnref
void xteValueUnref(XTE_Value objVal);
int xte_private_FreeTableProc(Hash32_Key* pKey, XTE_Value* ppVal, void* pArg)
{
	xteValueUnref(*ppVal);
	return FALSE;
}
void xteValueUnref(XTE_Value objVal)
{
	if ( objVal && (objVal != &XTE_VALUE_NULL) ) {
		objVal->RefCount--;
		// 引用计数用完了就销毁对象
		if ( objVal->RefCount == 0 ) {
			if ( objVal->MainType == XTE_DT_TEXT ) {
				free(objVal->vText);
			} else if ( objVal->MainType == XTE_DT_ARRAY ) {
				// 数组需要释放子元素
				for ( int i = 1; i <= objVal->vArray->Count; i++ ) {
					XTE_Value objVal = PAMM_GetVal_Unsafe(objVal->vArray, i);
					xteValueUnref(objVal);
				}
			} else if ( objVal->MainType == XTE_DT_TABLE ) {
				// 表需要释放子元素
				AVLHT32_Walk(objVal->vTable, (void*)xte_private_FreeTableProc, NULL);
			} else if ( objVal->MainType == XTE_DT_CUSTOM ) {
				// !!! ★★★ ------ 暂未实现本机制 ------ ★★★ !!!
				
			}
			free(objVal);
		}
	}
}

// 创建 Value
XTE_Value xteValueCreateNull()
{
	return &XTE_VALUE_NULL;
}
XTE_Value xteValueCreateBool(int bVal)
{
	XTE_Value objVal = malloc(sizeof(XTE_ValueStruct));
	objVal->MainType = XTE_DT_BOOL;
	objVal->SubType = 0;
	objVal->RefCount = 1;
	objVal->vBool = bVal;
	return objVal;
}
XTE_Value xteValueCreateInt(long long iVal)
{
	XTE_Value objVal = malloc(sizeof(XTE_ValueStruct));
	objVal->MainType = XTE_DT_INT;
	objVal->SubType = 0;
	objVal->RefCount = 1;
	objVal->vInt = iVal;
	return objVal;
}
XTE_Value xteValueCreateFloat(double fVal)
{
	XTE_Value objVal = malloc(sizeof(XTE_ValueStruct));
	objVal->MainType = XTE_DT_FLOAT;
	objVal->SubType = 0;
	objVal->RefCount = 1;
	objVal->vFloat = fVal;
	return objVal;
}
XTE_Value xteValueCreateText(char* sVal, int bColloc)
{
	XTE_Value objVal = malloc(sizeof(XTE_ValueStruct));
	objVal->MainType = XTE_DT_TEXT;
	objVal->SubType = 0;
	objVal->RefCount = 1;
	if ( bColloc ) {
		objVal->vText = sVal;
	} else {
		size_t iSize = strlen(sVal);
		objVal->vText = malloc(iSize + 1);
		memcpy(objVal->vText, sVal, iSize);
		objVal->vText[iSize] = 0;
	}
	return objVal;
}
XTE_Value xteValueCreateArray()
{
	XTE_Value objVal = malloc(sizeof(XTE_ValueStruct));
	objVal->MainType = XTE_DT_ARRAY;
	objVal->SubType = 0;
	objVal->RefCount = 1;
	objVal->vArray = PAMM_Create();
	return objVal;
}
XTE_Value xteValueCreateTable()
{
	XTE_Value objVal = malloc(sizeof(XTE_ValueStruct));
	objVal->MainType = XTE_DT_TABLE;
	objVal->SubType = 0;
	objVal->RefCount = 1;
	objVal->vTable = AVLHT32_Create(sizeof(void*));
	return objVal;
}
XTE_Value xteValueCreateCustom(void* pVal)
{
	XTE_Value objVal = malloc(sizeof(XTE_ValueStruct));
	objVal->MainType = XTE_DT_CUSTOM;
	objVal->SubType = 0;
	objVal->RefCount = 1;
	objVal->vCustom = pVal;
	return objVal;
}

// Value 读数据（最低转换度）
int xteValueGetBool(XTE_Value objVal)
{
	if ( objVal == NULL ) {
		return FALSE;
	} else if ( objVal->MainType == XTE_DT_BOOL ) {
		return objVal->vBool;
	} else if ( objVal->MainType == XTE_DT_INT ) {
		return objVal->vInt == 0 ? FALSE : TRUE;
	} else if ( objVal->MainType == XTE_DT_FLOAT ) {
		return objVal->vFloat == 0.0 ? FALSE : TRUE;
	} else if ( objVal->MainType == XTE_DT_NULL ) {
		return FALSE;
	} else {
		return TRUE;
	}
}
long long xteValueGetInt(XTE_Value objVal)
{
	if ( objVal == NULL ) {
		return 0;
	} else if ( objVal->MainType == XTE_DT_INT ) {
		return objVal->vInt;
	} else if ( objVal->MainType == XTE_DT_BOOL ) {
		return objVal->vBool ? 1 : 0;
	} else if ( objVal->MainType == XTE_DT_FLOAT ) {
		return objVal->vFloat;
	} else if ( objVal->MainType == XTE_DT_TEXT ) {
		return jnum_atol(objVal->vText);
	} else {
		return 0;
	}
}
double xteValueGetFloat(XTE_Value objVal)
{
	if ( objVal == NULL ) {
		return 0.0;
	} else if ( objVal->MainType == XTE_DT_INT ) {
		return objVal->vInt;
	} else if ( objVal->MainType == XTE_DT_BOOL ) {
		return objVal->vBool ? 1.0 : 0.0;
	} else if ( objVal->MainType == XTE_DT_FLOAT ) {
		return objVal->vFloat;
	} else if ( objVal->MainType == XTE_DT_TEXT ) {
		return jnum_atod(objVal->vText);
	} else {
		return 0.0;
	}
}
char* xteValueGetText(XTE_Value objVal)
{
	if ( objVal == NULL ) {
		return NULL;
	} else if ( objVal->MainType == XTE_DT_TEXT ) {
		return objVal->vText;
	} else if ( objVal->MainType == XTE_DT_BOOL ) {
		return objVal->vBool ? "true" : "false";
	} else if ( objVal->MainType == XTE_DT_INT ) {
		char sRet[32];
		jnum_ltoa(objVal->vInt, sRet);
		return sRet;
	} else if ( objVal->MainType == XTE_DT_FLOAT ) {
		char sRet[32];
		jnum_dtoa(objVal->vFloat, sRet);
		return sRet;
	} else if ( objVal->MainType == XTE_DT_ARRAY ) {
		char sRet[32];
		sprintf(sRet, "[array:%x]", objVal->vArray);
		return sRet;
	} else if ( objVal->MainType == XTE_DT_TABLE ) {
		char sRet[32];
		sprintf(sRet, "[table:%x]", objVal->vTable);
		return sRet;
	} else if ( objVal->MainType == XTE_DT_CUSTOM ) {
		char sRet[32];
		sprintf(sRet, "[custom:%x]", objVal->vCustom);
		return sRet;
	} else {
		return NULL;
	}
}
PAMM_Object xteValueGetArray(XTE_Value objVal)
{
	if ( objVal == NULL ) {
		return NULL;
	} else if ( objVal->MainType == XTE_DT_ARRAY ) {
		return objVal->vArray;
	} else {
		return NULL;
	}
}
AVLHT32_Object xteValueGetTable(XTE_Value objVal)
{
	if ( objVal == NULL ) {
		return NULL;
	} else if ( objVal->MainType == XTE_DT_TABLE ) {
		return objVal->vTable;
	} else {
		return NULL;
	}
}
void* xteValueGetCustom(XTE_Value objVal)
{
	if ( objVal == NULL ) {
		return NULL;
	} else if ( objVal->MainType == XTE_DT_CUSTOM ) {
		return objVal->vCustom;
	} else {
		return NULL;
	}
}

// Table 读 Key 操作
XTE_Value xteTableGetValue(XTE_Value tblVal, char* sKey, unsigned int iSize)
{
	if ( tblVal == NULL ) {
		return &XTE_VALUE_NULL;
	}
	if ( tblVal->MainType != XTE_DT_TABLE ) {
		return &XTE_VALUE_NULL;
	}
	if ( iSize == 0 ) {
		iSize = strlen(sKey);
	}
	XTE_Value objVal = AVLHT32_GetPtr(tblVal->vTable, sKey, iSize);
	if ( objVal ) {
		return objVal;
	} else {
		return &XTE_VALUE_NULL;
	}
}
int xteTableGetBool(XTE_Value tblVal, char* sKey, unsigned int iSize)
{
	return xteValueGetBool(xteTableGetValue(tblVal, sKey, iSize));
}
long long xteTableGetInt(XTE_Value tblVal, char* sKey, unsigned int iSize)
{
	return xteValueGetInt(xteTableGetValue(tblVal, sKey, iSize));
}
double xteTableGetFloat(XTE_Value tblVal, char* sKey, unsigned int iSize)
{
	return xteValueGetFloat(xteTableGetValue(tblVal, sKey, iSize));
}
char* xteTableGetText(XTE_Value tblVal, char* sKey, unsigned int iSize)
{
	return xteValueGetText(xteTableGetValue(tblVal, sKey, iSize));
}
PAMM_Object xteTableGetArray(XTE_Value tblVal, char* sKey, unsigned int iSize)
{
	return xteValueGetArray(xteTableGetValue(tblVal, sKey, iSize));
}
AVLHT32_Object xteTableGetTable(XTE_Value tblVal, char* sKey, unsigned int iSize)
{
	return xteValueGetTable(xteTableGetValue(tblVal, sKey, iSize));
}
void* xteTableGetCustom(XTE_Value tblVal, char* sKey, unsigned int iSize)
{
	return xteValueGetCustom(xteTableGetValue(tblVal, sKey, iSize));
}

// Table 写 Key 操作
int xteTableSetValue(XTE_Value tblVal, char* sKey, unsigned int iSize, XTE_Value objNewVal, int bColloc)
{
	if ( tblVal == NULL ) {
		return FALSE;
	}
	if ( tblVal->MainType != XTE_DT_TABLE ) {
		return FALSE;
	}
	if ( iSize == 0 ) {
		iSize = strlen(sKey);
	}
	XTE_Value objOldVal;
	int bRet = AVLHT32_SetPtr(tblVal->vTable, sKey, iSize, objNewVal, (void**)&objOldVal);
	if ( bRet ) {
		if ( bColloc == FALSE ) {
			xteValueRef(objNewVal);
		}
		xteValueUnref(objOldVal);
		return TRUE;
	} else {
		return FALSE;
	}
}
int xteTableSetNull(XTE_Value tblVal, char* sKey, unsigned int iSize)
{
	return xteTableSetValue(tblVal, sKey, iSize, &XTE_VALUE_NULL, FALSE);
}
int xteTableSetBool(XTE_Value tblVal, char* sKey, unsigned int iSize, int bVal)
{
	return xteTableSetValue(tblVal, sKey, iSize, xteValueCreateBool(bVal), TRUE);
}
int xteTableSetInt(XTE_Value tblVal, char* sKey, unsigned int iSize, long long iVal)
{
	return xteTableSetValue(tblVal, sKey, iSize, xteValueCreateInt(iVal), TRUE);
}
int xteTableSetFloat(XTE_Value tblVal, char* sKey, unsigned int iSize, double fVal)
{
	return xteTableSetValue(tblVal, sKey, iSize, xteValueCreateFloat(fVal), TRUE);
}
int xteTableSetText(XTE_Value tblVal, char* sKey, unsigned int iSize, char* sVal, int bColloc)
{
	return xteTableSetValue(tblVal, sKey, iSize, xteValueCreateText(sVal, bColloc), TRUE);
}
int xteTableSetArray(XTE_Value tblVal, char* sKey, unsigned int iSize)
{
	return xteTableSetValue(tblVal, sKey, iSize, xteValueCreateArray(), TRUE);
}
int xteTableSetTable(XTE_Value tblVal, char* sKey, unsigned int iSize)
{
	return xteTableSetValue(tblVal, sKey, iSize, xteValueCreateTable(), TRUE);
}
int xteTableSetCustom(XTE_Value tblVal, char* sKey, unsigned int iSize, void* pVal)
{
	return xteTableSetValue(tblVal, sKey, iSize, xteValueCreateCustom(pVal), TRUE);
}

// 表操作
int xteTableExists(XTE_Value tblVal, char* sKey, unsigned int iSize)
{
	if ( tblVal == NULL ) {
		return FALSE;
	}
	if ( tblVal->MainType != XTE_DT_TABLE ) {
		return FALSE;
	}
	if ( iSize == 0 ) {
		iSize = strlen(sKey);
	}
	return AVLHT32_Exists(tblVal->vTable, sKey, iSize);
}
int xteTableItemCount(XTE_Value tblVal)
{
	if ( tblVal == NULL ) {
		return 0;
	}
	if ( tblVal->MainType != XTE_DT_TABLE ) {
		return 0;
	}
	return AVLHT32_Count(tblVal->vTable);
}
int xteTableClear(XTE_Value tblVal)
{
	if ( tblVal == NULL ) {
		return FALSE;
	}
	if ( tblVal->MainType != XTE_DT_TABLE ) {
		return FALSE;
	}
	AVLHT32_Walk(tblVal->vTable, (void*)xte_private_FreeTableProc, NULL);
	AVLHT32_Clear(tblVal->vTable);
	return TRUE;
}

// Array 读操作（索引从 0 开始）
XTE_Value xteArrayGetValue(XTE_Value arrVal, unsigned int idx)
{
	if ( arrVal == NULL ) {
		return &XTE_VALUE_NULL;
	}
	if ( arrVal->MainType != XTE_DT_ARRAY ) {
		return &XTE_VALUE_NULL;
	}
	XTE_Value objVal = PAMM_GetVal(arrVal->vArray, idx + 1);
	if ( objVal ) {
		return objVal;
	} else {
		return &XTE_VALUE_NULL;
	}
}
int xteArrayGetBool(XTE_Value arrVal, unsigned int idx)
{
	return xteValueGetBool(xteArrayGetValue(arrVal, idx));
}
long long xteArrayGetInt(XTE_Value arrVal, unsigned int idx)
{
	return xteValueGetInt(xteArrayGetValue(arrVal, idx));
}
double xteArrayGetFloat(XTE_Value arrVal, unsigned int idx)
{
	return xteValueGetFloat(xteArrayGetValue(arrVal, idx));
}
char* xteArrayGetText(XTE_Value arrVal, unsigned int idx)
{
	return xteValueGetText(xteArrayGetValue(arrVal, idx));
}
PAMM_Object xteArrayGetArray(XTE_Value arrVal, unsigned int idx)
{
	return xteValueGetArray(xteArrayGetValue(arrVal, idx));
}
AVLHT32_Object xteArrayGetTable(XTE_Value arrVal, unsigned int idx)
{
	return xteValueGetTable(xteArrayGetValue(arrVal, idx));
}
void* xteArrayGetCustom(XTE_Value arrVal, unsigned int idx)
{
	return xteValueGetCustom(xteArrayGetValue(arrVal, idx));
}

// Array 追加操作
int xteArrayAppendValue(XTE_Value arrVal, XTE_Value objNewVal, int bColloc)
{
	if ( arrVal == NULL ) {
		return FALSE;
	}
	if ( arrVal->MainType != XTE_DT_ARRAY ) {
		return FALSE;
	}
	PAMM_Append(arrVal->vArray, objNewVal);
	if ( bColloc == FALSE ) {
		xteValueRef(objNewVal);
	}
	return TRUE;
}
int xteArrayAppendNull(XTE_Value arrVal)
{
	return xteArrayAppendValue(arrVal, &XTE_VALUE_NULL, FALSE);
}
int xteArrayAppendBool(XTE_Value arrVal, int bVal)
{
	return xteArrayAppendValue(arrVal, xteValueCreateBool(bVal), TRUE);
}
int xteArrayAppendInt(XTE_Value arrVal, long long iVal)
{
	return xteArrayAppendValue(arrVal, xteValueCreateInt(iVal), TRUE);
}
int xteArrayAppendFloat(XTE_Value arrVal, double fVal)
{
	return xteArrayAppendValue(arrVal, xteValueCreateFloat(fVal), TRUE);
}
int xteArrayAppendText(XTE_Value arrVal, char* sVal, int bColloc)
{
	return xteArrayAppendValue(arrVal, xteValueCreateText(sVal, bColloc), TRUE);
}
int xteArrayAppendArray(XTE_Value arrVal)
{
	return xteArrayAppendValue(arrVal, xteValueCreateArray(), TRUE);
}
int xteArrayAppendTable(XTE_Value arrVal)
{
	return xteArrayAppendValue(arrVal, xteValueCreateTable(), TRUE);
}
int xteArrayAppendCustom(XTE_Value arrVal, void* pVal)
{
	return xteArrayAppendValue(arrVal, xteValueCreateCustom(pVal), TRUE);
}

// Array 插入操作
int xteArrayInsertValue(XTE_Value arrVal, unsigned int idx, XTE_Value objNewVal, int bColloc)
{
	if ( arrVal == NULL ) {
		return FALSE;
	}
	if ( arrVal->MainType != XTE_DT_ARRAY ) {
		return FALSE;
	}
	PAMM_Insert(arrVal->vArray, idx, objNewVal);
	if ( bColloc == FALSE ) {
		xteValueRef(objNewVal);
	}
	return TRUE;
}
int xteArrayInsertNull(XTE_Value arrVal, unsigned int idx)
{
	return xteArrayInsertValue(arrVal, idx, &XTE_VALUE_NULL, FALSE);
}
int xteArrayInsertBool(XTE_Value arrVal, unsigned int idx, int bVal)
{
	return xteArrayInsertValue(arrVal, idx, xteValueCreateBool(bVal), TRUE);
}
int xteArrayInsertInt(XTE_Value arrVal, unsigned int idx, long long iVal)
{
	return xteArrayInsertValue(arrVal, idx, xteValueCreateInt(iVal), TRUE);
}
int xteArrayInsertFloat(XTE_Value arrVal, unsigned int idx, double fVal)
{
	return xteArrayInsertValue(arrVal, idx, xteValueCreateFloat(fVal), TRUE);
}
int xteArrayInsertText(XTE_Value arrVal, unsigned int idx, char* sVal, int bColloc)
{
	return xteArrayInsertValue(arrVal, idx, xteValueCreateText(sVal, bColloc), TRUE);
}
int xteArrayInsertArray(XTE_Value arrVal, unsigned int idx)
{
	return xteArrayInsertValue(arrVal, idx, xteValueCreateArray(), TRUE);
}
int xteArrayInsertTable(XTE_Value arrVal, unsigned int idx)
{
	return xteArrayInsertValue(arrVal, idx, xteValueCreateTable(), TRUE);
}
int xteArrayInsertCustom(XTE_Value arrVal, unsigned int idx, void* pVal)
{
	return xteArrayInsertValue(arrVal, idx, xteValueCreateCustom(pVal), TRUE);
}

// Array 写操作（元素必须已存在）
int xteArraySetValue(XTE_Value arrVal, unsigned int idx, XTE_Value objNewVal, int bColloc)
{
	if ( arrVal == NULL ) {
		return FALSE;
	}
	if ( arrVal->MainType != XTE_DT_ARRAY ) {
		return FALSE;
	}
	XTE_Value objOldVal = PAMM_GetVal(arrVal->vArray, idx + 1);
	PAMM_SetVal(arrVal->vArray, idx + 1, objNewVal);
	if ( bColloc == FALSE ) {
		xteValueRef(objNewVal);
	}
	xteValueUnref(objOldVal);
	return TRUE;
}
int xteArraySetNull(XTE_Value arrVal, unsigned int idx)
{
	return xteArraySetValue(arrVal, idx, &XTE_VALUE_NULL, FALSE);
}
int xteArraySetBool(XTE_Value arrVal, unsigned int idx, int bVal)
{
	return xteArraySetValue(arrVal, idx, xteValueCreateBool(bVal), TRUE);
}
int xteArraySetInt(XTE_Value arrVal, unsigned int idx, long long iVal)
{
	return xteArraySetValue(arrVal, idx, xteValueCreateInt(iVal), TRUE);
}
int xteArraySetFloat(XTE_Value arrVal, unsigned int idx, double fVal)
{
	return xteArraySetValue(arrVal, idx, xteValueCreateFloat(fVal), TRUE);
}
int xteArraySetText(XTE_Value arrVal, unsigned int idx, char* sVal, int bColloc)
{
	return xteArraySetValue(arrVal, idx, xteValueCreateText(sVal, bColloc), TRUE);
}
int xteArraySetArray(XTE_Value arrVal, unsigned int idx)
{
	return xteArraySetValue(arrVal, idx, xteValueCreateArray(), TRUE);
}
int xteArraySetTable(XTE_Value arrVal, unsigned int idx)
{
	return xteArraySetValue(arrVal, idx, xteValueCreateTable(), TRUE);
}
int xteArraySetCustom(XTE_Value arrVal, unsigned int idx, void* pVal)
{
	return xteArraySetValue(arrVal, idx, xteValueCreateCustom(pVal), TRUE);
}

// 数组操作
int xteArraySwap(XTE_Value arrVal, unsigned int idx1, unsigned int idx2)
{
	if ( arrVal == NULL ) {
		return FALSE;
	}
	if ( arrVal->MainType != XTE_DT_ARRAY ) {
		return FALSE;
	}
	return PAMM_Swap(arrVal->vArray, idx1 + 1, idx2 + 1);
}
int xteArrayRemove(XTE_Value arrVal, unsigned int idx, unsigned int iCount)
{
	if ( arrVal == NULL ) {
		return FALSE;
	}
	if ( arrVal->MainType != XTE_DT_ARRAY ) {
		return FALSE;
	}
	XTE_Value objOldVal = PAMM_GetVal(arrVal->vArray, idx + 1);
	xteValueUnref(objOldVal);
	return PAMM_Remove(arrVal->vArray, idx + 1, iCount);
}
int xteArrayItemCount(XTE_Value arrVal)
{
	if ( arrVal == NULL ) {
		return 0;
	}
	if ( arrVal->MainType != XTE_DT_ARRAY ) {
		return 0;
	}
	return arrVal->vArray->Count;
}
int xteArrayClear(XTE_Value arrVal)
{
	if ( arrVal == NULL ) {
		return FALSE;
	}
	if ( arrVal->MainType != XTE_DT_ARRAY ) {
		return FALSE;
	}
	for ( int i = 1; i <= arrVal->vArray->Count; i++ ) {
		XTE_Value objVal = PAMM_GetVal_Unsafe(arrVal->vArray, i);
		xteValueUnref(objVal);
	}
	PAMM_Clear(arrVal->vArray);
	return TRUE;
}

// 类型操作
int xteValueType(XTE_Value varVal)
{
	if ( varVal == NULL ) {
		return XTE_DT_NULL;
	} else if ( varVal == &XTE_VALUE_NULL ) {
		return XTE_DT_NULL;
	} else {
		return varVal->MainType;
	}
}
int xteTableItemType(XTE_Value varVal, char* sKey, unsigned int iSize)
{
	return xteValueType(xteTableGetValue(varVal, sKey, iSize));
}
int xteArrayItemType(XTE_Value varVal, unsigned int idx)
{
	return xteValueType(xteArrayGetValue(varVal, idx));
}



// 根据 XTE_LiteObject 模板对象生成文档
char* xteLiteMake(XTE_LiteObject objTemplate, XTE_Value tblVal, AVLHT32_Object tblInclude)
{
	// 检查环境表
	if ( tblVal == NULL ) {
		return NULL;
	}
	if ( tblVal->MainType != XTE_DT_TABLE ) {
		return NULL;
	}
	// 申请自增长缓冲区
	MBMU_Object objBuf = MBMU_Create(65536, 65536);
	if ( objBuf == NULL ) {
		return NULL;
	}
	// 遍历模板 Action 生成内容
	for ( int i = 1; i <= objTemplate->Actions.Count; i++ ) {
		XTE_TokenItem objTok = (XTE_TokenItem)PAMM_GetVal_Unsafe(&objTemplate->Actions, i);
		if ( objTok->Type == XTE_TK_TEXT ) {
			// 文本节点
			MBMU_Append(objBuf, objTok->Text, objTok->Size, MBMU_UTF8);
		} else if ( objTok->Type == XTE_TK_VAR ) {
			// 代入变量
			char* sTemp = xteTableGetText(tblVal, objTok->Text, objTok->Size);
			if ( sTemp ) {
				MBMU_Append(objBuf, sTemp, 0, MBMU_UTF8);
			} else {
				MBMU_Append(objBuf, "null", 4, MBMU_UTF8);
			}
		} else if ( objTok->Type == XTE_TK_NUM ) {
			// 代入数字
			char* sTemp = xteTableGetText(tblVal, objTok->Text, objTok->Size);
			if ( sTemp ) {
				MBMU_Append(objBuf, sTemp, 0, MBMU_UTF8);
			} else {
				MBMU_Append(objBuf, "null", 4, MBMU_UTF8);
			}
		} else if ( objTok->Type == XTE_TK_TIME ) {
			// 代入时间（暂不支持）
			printf("\t★★★ Token Type [%d] : XTE_TK_TIME (%d)\n", i, objTok->Type);
		} else if ( objTok->Type == XTE_TK_BOOL ) {
			// 代入逻辑类型
			char* sTemp = xteTableGetText(tblVal, objTok->Text, objTok->Size);
			MBMU_Append(objBuf, sTemp, 0, MBMU_UTF8);
		} else if ( objTok->Type == XTE_TK_ARR ) {
			// 遍历元素 表 or 数组
			printf("\t★★★ Token Type [%d] : XTE_TK_ARR (%d)\n", i, objTok->Type);
		} else if ( objTok->Type == XTE_TK_PROC ) {
			// 调用函数
			printf("\t★★★ Token Type [%d] : XTE_TK_PROC (%d)\n", i, objTok->Type);
		} else if ( objTok->Type == XTE_TK_SUBTEMPLATE ) {
			// 代入子模板
			printf("\t★★★ Token Type [%d] : XTE_TK_SUBTEMPLATE (%d)\n", i, objTok->Type);
		} else if ( objTok->Type == XTE_TK_INCLUDE ) {
			// 引用外部模板
			printf("\t★★★ Token Type [%d] : XTE_TK_INCLUDE (%d)\n", i, objTok->Type);
		} else if ( objTok->Type == XTE_TK_SCRIPT ) {
			// 执行脚本
			printf("\t★★★ Token Type [%d] : XTE_TK_SCRIPT (%d)\n", i, objTok->Type);
		} else {
			printf("\t★★★ Error : Unknown Token Type ID [%d] : %d\n", i, objTok->Type);
		}
	}
	// 移出 objBuf->Buffer 返回，销毁 objBuf
	char* sRet = objBuf->Buffer;
	objBuf->Buffer = NULL;
	MBMU_Destroy(objBuf);
	return sRet;
}


